﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using Axiom.Core;

namespace GameDesigner
{
    public class TypeConverters
    {

        /// <summary>
        /// Adds the TypeConverterAttribute TC, to class T
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TC"></typeparam>
        protected static void RegisterTypeConverter<T, TC>() where TC : TypeConverter
        {
            Attribute[] attr = new Attribute[1];
            TypeConverterAttribute vConv = new TypeConverterAttribute(typeof(TC));
            attr[0] = vConv;
            TypeDescriptor.AddAttributes(typeof(T), attr);
        }

        public static void SetConverters()
        {
            RegisterTypeConverter<Axiom.Math.Vector3, Vector3TypeConverter>();
            RegisterTypeConverter<Axiom.Core.Mesh, MeshTypeConverter>();
        }

        public class Vector3TypeConverter : TypeConverter
        {

            public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
            {
                if (destinationType == typeof(Axiom.Math.Vector3))
                    return true;

                return base.CanConvertTo(context, destinationType);
            }

            public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
            {
                if (destinationType == typeof(String) && value is Axiom.Math.Vector3)
                {
                    return ((Axiom.Math.Vector3)value).ToString();
                }
                return base.ConvertTo(context, culture, value, destinationType);
            }

            public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
            {
                if (sourceType == typeof(String))
                    return true;

                return base.CanConvertFrom(context, sourceType);
            }

            public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
            {
                if (value is String)
                    return Axiom.Math.Vector3.Parse((string)value);

                return base.ConvertFrom(context, culture, value);
            }

            public override bool GetPropertiesSupported(ITypeDescriptorContext context)
            {
                return false;
            }
        }

        public class MeshTypeConverter : TypeConverter
        {

            public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
            {
                if (destinationType == typeof(string))
                    return true;

                return base.CanConvertTo(context, destinationType);
            }

            public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
            {
                if (destinationType == typeof(String) && value is Axiom.Core.Mesh)
                {
                    return ((Axiom.Core.Mesh)value).Name;
                }

                return base.ConvertTo(context, culture, value, destinationType);
            }

            public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
            {
                if (sourceType == typeof(String))
                    return true;

                return base.CanConvertFrom(context, sourceType);
            }

            public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
            {
                //TODO: check if it is not loaded load it, otherwise it will reload
                if (value is String)
                    return Axiom.Core.MeshManager.Instance.Load(
                        (string)value,
                        Axiom.Core.ResourceGroupManager.AutoDetectResourceGroupName);

                return base.ConvertFrom(context, culture, value);
            }

            public override bool GetPropertiesSupported(ITypeDescriptorContext context)
            {
                return false;
            }

            public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
            {
                //true means show a combobox
                return true;
            }

            public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
            {
                //true will limit to list. false will allow free-form entry
                return true;
            }

            public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
            {
                ResourceGroupManager ResManager = ResourceGroupManager.Instance;
                List<string> Meshes = new List<string>();

                foreach (string group in ResManager.GetResourceGroups())
                    if (group != "AGDRes")
                        foreach (string mesh in ResManager.FindResourceNames(group, "*.mesh"))
                            Meshes.Add(mesh);

                return new StandardValuesCollection(Meshes);
            }
        }

        public class ResourceGroupsTypeConverter : TypeConverter
        {
            public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
            {
                if (sourceType == typeof(String))
                    return true;

                return base.CanConvertFrom(context, sourceType);
            }

            public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
            {
                if (value is string)
                    return value;

                return base.ConvertFrom(context, culture, value);
            }

            public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
            {
                if (destinationType == typeof(String))
                    return true;

                return base.CanConvertTo(context, destinationType);
            }

            public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
            {
                if (destinationType == typeof(String))
                    return value;

                return base.ConvertTo(context, culture, value, destinationType);
            }

            public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
            {
                List<string> groups = ResourceGroupManager.Instance.GetResourceGroups();
                if (groups.Contains("AGDRes"))
                    groups.Remove("AGDRes");

                return new StandardValuesCollection(groups);
            }

            public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
            {
                return true;
            }
        }

        public class ResourceTypeTypeConverter : TypeConverter
        {
            public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
            {
                List<string> Types = new List<string>(2);
                Types.Add("ZipFile");
                Types.Add("Folder");

                return new StandardValuesCollection(Types);
            }

            public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
            {
                return true;
            }

            public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
            {
                return true;
            }
        }

        public class YesNoValueTypeConverter : TypeConverter
        {
            public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
            {
                List<string> Types = new List<string>(2);
                Types.Add("yes");
                Types.Add("no");

                return new StandardValuesCollection(Types);
            }

            public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
            {
                return true;
            }

            public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
            {
                return true;
            }
        }

    }

}
